﻿using System;
using System.Collections.Generic;
using System.Reflection;
using net.entity.framework.common;

namespace net.entity.framework.cache {
    internal static class EqlEntityRefCache {
        #region Members

        private static readonly Dictionary<Type, EqlEntityInfo> cache = new Dictionary<Type, EqlEntityInfo>();

        #endregion

        #region Methods

        /// <summary>
        /// Lookup or Create the cache for EqlEntityRef
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        internal static EqlEntityInfo LookupOrCreate<T>() where T : EntityRef {
            var type = typeof (T);
            return LookupOrCreate(type);
        }

        /// <summary>
        /// Lookup or Create the cache for EqlEntityRef type
        /// </summary>
        /// <param name="entityRefType">EqlEntityRef type</param>
        /// <returns></returns>
        internal static EqlEntityInfo LookupOrCreate(Type entityRefType) {
            return cache.LookupOrCreate(entityRefType, EqlEntityInfo.Create);
        }

        #endregion
    }

    internal sealed class EqlEntityInfo {
        private const BindingFlags Flags = BindingFlags.Public | BindingFlags.Static;

        #region Properties

        internal EqlEntityRef EqlEntityRef { get; set; }
        internal EqlEntity EqlEntity { get; set; }

        #endregion

        #region Constructor/Initialiser

        internal EqlEntityInfo(EqlEntityRef entityRef, EqlEntity entity) {
            EqlEntityRef = entityRef;
            EqlEntity = entity;
        }

        internal static EqlEntityInfo Create(Type entityRefType) {
            var queryRoot = entityRefType.GetPropertyInfo("QueryRoot", Flags, true);
            var eqlEntityRef = queryRoot.GetValue<EqlEntityRef>(true);
            var eqlEntity = eqlEntityRef.GetPropertyValue<EqlEntity>("T", true);
            return new EqlEntityInfo(eqlEntityRef, eqlEntity);
        }

        #endregion
    }
}